<?php
/**
 * @todo This user module does not follow strictly the convention of Clu framework.
 * @abstract 
 *     user status: 0 = not activated
 *                  1 = activated
 *                  2 = suspended
 * 					[TODO: payment status]
 */

class user_Model_User extends Zend_Db_Table_Abstract  
{
    protected $_name = 'users';
    protected $_id = 'id';
    public function findByPrimary($id)
	{
		if ($id === null)
            return null;
        else
		    return $this->fetchRow('id = ' . $this->getAdapter()->quote($id, 'INTEGER'));
	}
    
    /**
     * @abstract Add some salt&pepper before hashing it with sha256
     */
    
    public static function computePasswordHash($password)
    {
        return hash('sha256', 'salt' . $password . 'pepper');
    }
 
     /**
     * Adds user to database, sends confirmation email
     *
     * @param string $username
     * @param string $password
     * @param string $email
     * @throws Zend_Db_Statement_Exception
     * @return int The id of the new user     
     */    
    public function insertRaw($data)
    {
        $userId = -1;
        $activationCode = sha1(uniqid('xyz', true)); 
 		$sess = new Zend_Session_Namespace(CLU_NS);
        $newUser = array(
            'name' => $data['name'],
            'pass' => $this->computePasswordHash($data['pass']),
            'mail' => $data['mail'],
            'activation_code' => $activationCode,
        	'language' => $sess->viewLang, 
            'created' => new Zend_Db_Expr('NOW()'),
            'type' => $data['type']
        );
        if (Zend_Registry::get('configuration')->development)
        {
        	$newUser['status'] = 1;
        }
        try {
	        $userId = $this->insert($newUser);
	        //$userId = 2;
	        //assign anonymous role to the user
	        //see AccountController Abstract
	        if ($userId > 1)
	        {
	        	//assign to 'registered user' role right away if development mode
	        	//$roleId =  get_key('registered_user_role_id');
			    $roleId =  get_key('anonymous_role_id');
		        if ($roleId)
                    $sql = "INSERT INTO user_roles (uid,rid) VALUES(".$this->getDefaultAdapter()->quote($userId, 'INTEGER').",$roleId)";
				$this->getDefaultAdapter()->query($sql);
	        }    
	        return $userId;
        }
        catch (Exception $e)
        {
        	echo $e->getMessage();
        	return false;
        }
    }

    /*
     * Just save normal profile data. No password involved
     */
	public function saveRaw($u, $data, $id, $doValidate)
	{
	    if ((!$u) && (!$id))
	    	return false;
	    else if (!$u || is_array($u))
	       	if (!$u = $this->findByPrimary($id))
	       		return false;
		
	    if (isset($data['pass']))
	    	$data['pass'] = $this->computePasswordHash($data['pass']);
	    	
	    if ($doValidate)
	    {
	    	//Validate Data here
	    }
		
		if(isset($data['status']))
			$data['status'] = $data['status'];
			
	    if(isset($data['account_type']))
	    	$data['type'] = $data['account_type'];
	    
	    if ($u->status != 0 && isset($data['status']))
			$data['upgrade_to'] = $data['status'];	
		
	    $u->setFromArray($data);
        return $u->save();
	}
	
	//get user info from 'users' table & other data such as
	//how many articles posted, where user has participated (commenting and such..)
    public function getUserData($id)
    {
    	if (!$u = $this->findByPrimary($id))
            return null;
		else
			return $u;
    }
    
    /**
	 * @abstract: Insert new roles for user into `user_roles` table
	 * @param: userRoleIds: Array of user role Ids that user $uid will have
	 * @return: Boolean for success or not
	 */
	public function insertUserRoles($uid, $userRoleIds)
	{
		$db = $this->getAdapter();
        $db->beginTransaction();
        try 
        {
			//delete all current user_roles related to $uid
	        $sql = "DELETE FROM user_roles WHERE uid=".$db->quote($uid, 'INTEGER');
	        $db->query($sql);
			foreach ($userRoleIds as $rid)
			{
				$sql = "INSERT INTO user_roles (`uid`, `rid`) VALUES(".$db->quote($uid, 'INTEGER').",".$db->quote($rid, 'INTEGER').")";
	        	$db->query($sql);
			}
        }
        catch (Exception $e)
        {
            $db->rollBack();
            return false;
        }
		return true;
	}
    
    /**
	* @return the list of roles of user: "2,3,4" 
	*/

    public function getUserRoles($id)
    {
    	$db = $this->getAdapter();
   		$sql = "SELECT rid FROM user_roles WHERE uid=" . $db->quote($id, 'INTEGER');
        $rowSet = $db->fetchAll($sql);
        $roleList = '';
	    foreach ($rowSet as $r) 
    	    $roleList .= $r['rid'].',' ;
		return rtrim($roleList,',');    
    }
    
    

    public function search($data)
    {
    	$db = $this->getAdapter();
    	$keys = array('id','name','mail', 'status');
        $t = clu_array_merge($keys, $data);
        $t['mail'] = $data['email'];
		//select SQL query
		$select = $db->select();
		
		// Add a FROM clause
        $select->from( array('u' => 'users'));
        
        if($t['name'])
        {
        	$names = $t['name'];
        	$select->where('u.name LIKE ?', $db->quoteinto("%$names%","STRING"));
        }
        
        if($t['id'])
        	$select->where('u.id = ?', (int)$db->quote($t['id'],"INT"));

        if($data['email'])
            $select->where('u.mail = ?',$db->quoteinto($data['email'],"STRING"));

        if($t['status'] >= 0 && $t['status'] != 'all')
    		$select->where('u.status = ?', (int)$db->quote($t['status'],'INT'));
    	
    	if($data['role'])
    	{
    		$rname = $data['role'];
    		$select->join(array('r' => 'user_roles'), 'u.id = r.uid');
    		$select->join(array('pr' => 'permissions'), 'r.rid = pr.rid', array('perm'));
    		$select->where('pr.rname LIKE ?',$db->quoteinto("%$rname%","STRING"));
    	}
//    	die($select);
        return $select;
    }
    /**
     * @abstract Activate the user if he clicks activation link via email
     * 		Also add "registered user" role (#2) to this user
     * 
     * $u: a table row, returned by a findByPrimary() call
     */
    public function activateUser($u)
    {
    	//require_once (APP_PATH.'/library/common.php');
    	$db = $this->getAdapter();
        // activate the user
   try {
            $u->status = 1; 
            $u->save();
           // $role = Zend_Registry::get('configuration')->user->activated; 
             $roleId =  get_key('registered_user_role_id');
             $sql = "INSERT INTO user_roles (uid,rid) VALUES(".$db->quote($u->id, 'INTEGER').", $roleId)";
              $this->getAdapter()->query($sql);
			return true;
        }     
        catch (Exception $e)    
        {
        	return false;
        }    
    }
    
	/*
	 * $idArray:: Array of primary keys
	 */
	public function deleteByPrimary($idArray)
	{
        $db = $this->getAdapter();
        $db->beginTransaction(); //@NOTE: no effect with MyISAM
        try
        {
            $sql = "DELETE u, ur FROM users u, user_roles ur WHERE u.id = ur.uid AND u.id IN (". $db->quote($idArray, 'INTEGER') .")" ;
           	$db->query($sql);
            $db->commit();
            return true;
    	}
        catch (Exception $e)
        {
            $db->rollBack();
            return false;
        }
	}
	
    	/**
	 * @abstract:  
	 */
	public function getUserRoleData($user)
	{
		$sql = "SELECT p.rname FROM permissions p, user_roles ur WHERE p.rid=ur.rid AND ur.uid=" . $this->getAdapter()->quote($user['id']); 
        $rowset = $this->getAdapter()->query($sql);
        $roles = $rowset->fetchAll();
        return $roles;
	}
    
    public function getCurrentUserRoleIds($uid)
	{ 
        //current user_roles
        $db = $this->getAdapter();
        $sql = "SELECT rid FROM user_roles WHERE uid=".$db->quote($uid, 'INTEGER') ;
        $userRowset = $db->query($sql);
        $userRoles = $userRowset->fetchAll();
        return $userRoles;
	}
    
    public function saveBillingInfo($u, $data)
    {
    	$a = array();
	    if(!empty($u->billing))
	    {
	    	if(!isset($data['number']))
	    	{
		    	$a['profileName'] = $data['billingProfileName'];
		    	$a['address'] = $data['billingAddress'];
		    	$a['payment_method'] = $data['payment_method'];
		    	if(isset($data['account_type']) && $data['account_type'] != 'none')
		    		$a['account_type'] = $data['account_type'];
		    	if(isset($data['expiry_date']))
		    		$a['expiry_date'] = $data['expiry_date'];
		    	if(isset($data['verificationCode']))
		    		$a['verification_code'] = $data['verificationCode'];
		    	$a['account_name'] = $data['account_name'];
		    	$a['account_number'] = $data['account_number'];
				if(isset($data['bank']) && $data['bank'] != 'none')
					$a['bank'] = $data['bank'];
		    	$b = unserialize($u->billing);
	    		$k = count($b['billing']) - 1;
		    	$b['billing'][$k+1] = serialize($a);
		    	$data['billing'] = serialize($b);
	    	}
	    	else
	    	{
	    		$metadata = unserialize($u->billing);
	    		foreach($metadata['billing'] as $k =>$v)
		        {
		        	if($data['number'] == $k)
		        	{
			        	$dataDisplay = unserialize($v);
			        	if(isset($data['billingProfileName']))
			        		$a['profileName'] = $data['billingProfileName'];
			        	else if(isset($dataDisplay['profileName']))
			        		$a['profileName'] = $dataDisplay['profileName'];
			        	
			        	if(isset($data['billingAddress']))
					    	$a['address'] = $data['billingAddress'];
					    else if(isset($dataDisplay['address']))
					    	$a['address'] = $dataDisplay['address'];
					    	
					    if(isset($data['payment_method']))
				    		$a['payment_method'] = $data['payment_method'];
				    	else if(isset($dataDisplay['payment_method']))
				    		$a['payment_method'] = $dataDisplay['payment_method'];
				    	
				    	if(isset($data['account_type']) && $data['account_type'] != 'none')
				    		$a['account_type'] = $data['account_type'];
				    	else if(isset($dataDisplay['account_type']))
				    		$a['account_type'] = $dataDisplay['account_type'];
				    		
				    	if(isset($data['expiry_date']))
				    		$a['expiry_date'] = $data['expiry_date'];
				    	else if(isset($dataDisplay['expiry_date']))
				    		$a['expiry_date'] = $dataDisplay['expiry_date'];
				    		
				    	if(isset($data['verificationCode']))
				    		$a['verification_code'] = $data['verificationCode'];
				    	else if(isset($dataDisplay['verification_code']))
				    		$a['verification_code'] = $dataDisplay['verification_code'];
				    	
				    	if(isset($data['account_name']))
				    		$a['account_name'] = $data['account_name'];
				    	else if(isset($dataDisplay['account_name']))
				    		$a['account_name'] = $dataDisplay['account_name'];
				    		
				    	if(isset($data['account_number']))
				    		$a['account_number'] = $data['account_number'];
				    	else if(isset($dataDisplay['account_number']))
				    		$a['account_number'] = $dataDisplay['account_number'];
				    		
						if(isset($data['bank']) && $data['bank'] != 'none')
							$a['bank'] = $data['bank'];
						else if(isset($dataDisplay['bank']))
							$a['bank'] = $dataDisplay['bank'];
			    		
			    		$metadata['billing'][$k] = serialize($a);
			    		$data['billing'] = serialize($metadata);
		        	}
		        }
	    	}
	    }
	    else
	    {
	    	$a['profileName'] = $data['billingProfileName'];
	    	$a['address'] = $data['billingAddress'];
	    	$a['payment_method'] = $data['payment_method'];
	    	if(isset($data['account_type']) && $data['account_type'] != 'none')
	    		$a['account_type'] = $data['account_type'];
	    	if(isset($data['expiry_date']))
	    		$a['expiry_date'] = $data['expiry_date'];
	    	if(isset($data['verificationCode']))
	    		$a['verification_code'] = $data['verificationCode'];
	    	$a['account_name'] = $data['account_name'];
	    	$a['account_number'] = $data['account_number'];
	    	if(isset($data['bank']) && $data['bank'] != 'none')
	    		$a['bank'] = $data['bank'];
	    	$b['billing'][] = serialize($a);
	    	$data['billing'] = serialize($b);
	    }
//    	die_a($data);
	    
	    $u->setFromArray($data);
        return $u->save();
    }
	
	public function deleteBillingInfo($u, $number)
	{
    	$metadata = unserialize($u->billing);
		foreach($metadata['billing'] as $k =>$v)
        {
        	if($number == $k)
        	{
	    		unset($metadata['billing'][$k]);
        	}
    		$data['billing'] = serialize($metadata);
        }
    	$u->setFromArray($data);
        return $u->save();
	}
	
	/**
	 * A broader search than findByPrimary()
	 * ** Only works for simple & quick search **
	 * This is a kinda a hack? TODO: merge it into search functionality
	 * $key : name
	 * $val : value of user Name
	 * $valType: "INTEGER | STRING"
	 * $searchType: equal or like
	 */ 
    public function findByExpression($key, $val, $valType, $searchType)
	{
		if ($val === null)
            return null;
        else
        {
        	$tmp = $this->getAdapter()->quote($val, $valType);
        	$sql = $key . " ";
			if ($searchType == "equals")
				$sql = $sql . "=" . $tmp;
			elseif($searchType == "like")
				$sql = $sql . "like %".$tmp."%";         	
		    return $this->fetchRow($sql);
        }
	}
    
    public function getVisitorUser($userId, $order = null)
    {
    	$sql = "SELECT * FROM channel_visits WHERE user_id = " . $userId; 
    	if($order)
    		$sql .= " ORDER BY created desc";
    	return $this->getAdapter()->fetchAll($sql);
    }
    
    public function insertDbAfterView($user_id, $visitorId)
	{
		$userInfo = $this->findByPrimary($visitorId);
		$visitorName = $userInfo['name'];
		$created = time();
		$sql = "INSERT INTO channel_visits (user_id, visitor_id, visitor_name, created) VALUES($user_id, $visitorId, '$visitorName', $created)";
		try{
			$this->getAdapter()->query($sql);
		}
		catch(Exception $e)
		{
			
		}
	}
	
	public function changeUserStatusSearch()
	{
		$sql = "SELECT * FROM " . $this->_name . " WHERE status != 0";
		return $this->getAdapter()->fetchAll($sql);
	}
	
	public function updateChangeStatusForUser($id, $data)
	{
		$u = $this->findByPrimary($id);
		if($data['type'] == "unactivate")
		{
			$result = $this->getUserRoles($id);
			$rId = explode(',', $result);
			foreach($rId as $v)
			{
				if($v == get_key('registered_company_role_id'))
				{
					$sql = "DELETE ur FROM user_roles ur WHERE rid = " . $v . " AND uid = " . $id;
					try{
						$this->getDefaultAdapter()->query($sql);
			        }
					catch(Exception $e)
					{
						
					}	
				}
			}
		}
		else
		{
			if($data['type'] == 1)// && in_array($data['status'], array(2,3,4,5)))
				$roleId =  get_key('registered_company_role_id');
			else if($data['type'] == 2)// && $data['status'] == 1)
				$roleId =  get_key('registered_user_role_id');
			else if($data['status'] == 0)
				$roleId =  get_key('anonymous_role_id');
			
	        if (isset($roleId))
	            $sql = "INSERT INTO user_roles (uid, rid) VALUES($id, $roleId)";
	        else if($u->status == 2)
	        {
	        	$roleId = get_key('registered_company_role_id');
	        	$sql = "INSERT INTO user_roles (uid, rid) VALUES($id, $roleId)";
	        }
	        
	        try{
				$this->getDefaultAdapter()->query($sql);
	        }
			catch(Exception $e)
			{
				
			}		
		}
		
       	if (!$u)
       		return false;
       	else
       	{
       		if(!empty($data['upgrade_to']))
       		{
       			$data['status'] = $data['upgrade_to'];
       		}
       		else
       			$data['status'] = $u->status;
       		$u->setFromArray($data);
        	return $u->save();
       	}
	}
}
?>